package com.sls.nzdapplication.util;

import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author : niyujia
 * @description : 签名方法类
 * @date : 2024/11/26
 */
public class SignUtils {

    /**
     * 签名 HmacSHA256
     *
     * @param data 待签名的指定格式 String
     * @param key  signSecret
     * @return 签名
     */
    public static String generateSign(String data, String key) {
        Log.i("generate sign data:{}", data);
        return CodecUtils.hexString(data, key);
    }

    /**
     * 验签 HmacSHA256
     *
     * @param data 待签名的指定格式 String
     * @param key  signSecret
     * @param sign 签名
     * @return 验签结果是否一致
     */
    public static boolean validSign(String data, String key, String sign) {
        Log.i("valid sign data:{}", data);
        String generateSign = CodecUtils.hexString(data, key);
        if (generateSign.equals(sign)) {
            return true;
        } else {
//            Log.error("验签失败.服务端生成的sign:[{}],上报的sign:[{}],key:[{}],签名的data:[{}]",
//                    generateSign, sign, key, data);
            return false;
        }
    }


    /**
     * 使用方法入口
     * JSONString 转指定格式 String
     *
     * @param jsonString JSONString
     * @return 指定格式 String
     */
    public static String toSignString(String jsonString) {
        String result = objToString(JSON.parseObject(jsonString), "");
        return result.substring(0, result.length() - 1);
    }

    /**
     * 递归
     * JSON 对象转指定格式 String
     *
     * @param jsonObj JSON 对象
     * @param prefix  拼接前缀
     * @return 指定格式 String
     */
    public static String objToString(JSONObject jsonObj, String prefix) {
        List<String> keys = new ArrayList<>(jsonObj.keySet());
        Collections.sort(keys);

        StringBuilder result = new StringBuilder();
        for (String key : keys) {
            if ("sign".equals(key)) {
                continue; // 跳过 sign 字段
            }
            Object value = jsonObj.get(key);
            String newPrefix = prefix.isEmpty() ? key : prefix + "." + key;
            if (value instanceof JSONObject) {
                result.append(objToString((JSONObject) value, newPrefix));
            } else if (value instanceof JSONArray) {
                result.append(arrayToString((JSONArray) value, newPrefix));
            } else {
                result.append(newPrefix).append("=").append(value.toString()).append("&");
            }
        }

        return result.toString();
    }

    /**
     * 递归
     * JSON 数组转指定格式 String
     *
     * @param jsonArray JSON 数组
     * @param prefix    拼接前缀
     * @return 指定格式 String
     */
    private static String arrayToString(JSONArray jsonArray, String prefix) {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < jsonArray.size(); i++) {
            Object item = jsonArray.get(i);
            String newPrefix = prefix + "[" + i + "]";
            if (item instanceof JSONObject) {
                result.append(objToString((JSONObject) item, newPrefix));
            } else if (item instanceof JSONArray) {
                result.append(arrayToString((JSONArray) item, newPrefix));
            } else {
                result.append(newPrefix).append("=").append(item.toString()).append("&");
            }
        }
        return result.toString();
    }

    /**
     * 根据客户端硬件编码、公共 KEY 生成属于 客户端的签名 key
     *
     * @param hardwareCode 硬件编码
     * @return key 32位
     */
    public static String generateKey(String hardwareCode, String key) {
        return CodecUtils.hexMD5(CodecUtils.hexString(hardwareCode, key));
    }

    public static void main(String[] args) {
        // 示例 JSON 数据
        String jsonString = "{\n" +
                "\t\"c\": 3,\n" +
                "\t\"a\": [\n" +
                "\t\t1,\n" +
                "\t\t{\n" +
                "\t\t\t\"b\": 2,\n" +
                "\t\t\t\"d\": 4\n" +
                "\t\t}\n" +
                "\t],\n" +
                "\t\"e\": \"hello\",\n" +
                "\t\"f\": {\n" +
                "\t\t\"g\": 5,\n" +
                "\t\t\"h\": 6\n" +
                "\t},\n" +
                "\t\"sign\": \"signature\"\n" +
                "}";
        String result = toSignString(jsonString);
        System.out.println(result);
        // authType=&contactTel=&deviceId=&email=&endDate=&featureList[0].enabled=true&featureList[0].featureName=&featureList[1].enabled=false&featureList[1].featureName=&hardwareCode=&ip=&pkgSize=&pkghash=&sign=&softwareName=&startDate=&userName=&userType=&version=
    }
}
